local PermissionGroup = {}
PermissionGroup.__index = PermissionGroup

Tubes.PermissionGroup = Tubes.MakeConstructor (PermissionGroup)

function PermissionGroup:ctor (name, predicate)
	self.Name = name
	self.Owner = nil
	self.OwnerSteamID = nil
	self.FullName = name
	self.NiceName = name
	self.Predicate = predicate
	
	self.MemberSteamIDs = {}
	self.MemberCount = 0
	
	self.Singular = false
	
	Tubes.EventProvider (self)
	for _, ply in ipairs (player.GetAll ()) do
		if self:IsInGroup (nil, ply) then
			self:AddPlayer (ply)
		end
	end
end

function PermissionGroup:AddPlayer (ply)
	local SteamID = Tubes.GetPlayerSteamID (ply)
	if not self.MemberSteamIDs [SteamID] then
		self.MemberSteamIDs [SteamID] = true
		self.MemberCount = self.MemberCount + 1
	end
end

function PermissionGroup:GetCachedMemberCount ()
	return self.MemberCount
end

function PermissionGroup:GetCachedMemberIterator ()
	local Next, Table, Key = pairs (self.MemberSteamIDs)
	return function ()
		Key = Next (Table, Key)
		return Key
	end
end

function PermissionGroup:GetFullName ()
	return self.FullName or self.Name or ""
end

function PermissionGroup:GetIcon ()
	return self.Singular and "gui/t_silkicons/user" or "gui/t_silkicons/group"
end

function PermissionGroup:GetName ()
	return self.Name or ""
end

function PermissionGroup:GetNiceName ()
	return self.NiceName or self.Name or ""
end

function PermissionGroup:GetOwner ()
	return self.Owner
end

function PermissionGroup:GetOwnerSteamID ()
	return self.OwnerSteamID or ""
end

function PermissionGroup:GetPredicate ()
	return self.Predicate
end

function PermissionGroup:HasCachedMembers ()
	return next (self.MemberSteamIDs) and true or false
end

function PermissionGroup:IsInGroup (permissionBlock, ply)
	if self:IsInMemberCache (ply) then
		return true
	end
	if not self.Predicate then
		return false
	end
	return self.Predicate (permissionBlock, ply)
end

function PermissionGroup:IsInMemberCache (ply)
	if self.MemberSteamIDs [Tubes.GetPlayerSteamID (ply)] then
		return true
	end
end

function PermissionGroup:IsSingular ()
	return self.Singular
end

function PermissionGroup:RemovePlayer (ply)
	local SteamID = Tubes.GetPlayerSteamID (ply)
	if self.MemberSteamIDs [SteamID] then
		self.MemberSteamIDs [SteamID] = nil
		self.MemberCount = self.MemberCount - 1
	end
end

function PermissionGroup:SetFullName (name)
	self.FullName = name
end

function PermissionGroup:SetName (name)
	self.Name = name
end

function PermissionGroup:SetNiceName (name)
	self.NiceName = name
end

function PermissionGroup:SetOwner (owner)
	self.Owner = owner
	
	if type (owner) == "Player" then
		self.OwnerSteamID = Tubes.GetPlayerSteamID (owner)
	end
end

function PermissionGroup:SetPredicate (predicate)
	self.Predicate = predicate
end

function PermissionGroup:SetSingular (singular)
	self.Singular = singular
end